package com.lenovo.leos.filebrowser.engine.operation;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.Message;
import android.widget.Toast;

import com.lenovo.leos.filebrowser.R;
import com.lenovo.leos.filebrowser.engine.util.FileClipBoard;
import com.lenovo.leos.filebrowser.engine.util.FileHandler;
import com.lenovo.leos.filebrowser.engine.util.FileThread;
import com.lenovo.leos.filebrowser.engine.util.FileUtil;
import com.lenovo.leos.filebrowser.engine.util.Log;
import com.lenovo.leos.filebrowser.netdisk.NetDiskManager;
import com.lenovo.leos.filebrowser.ui.BaseActivity;
import com.lenovo.leos.filebrowser.ui.FileDialog;

public class FileDelete {
	private static final String TAG = "FileDelete";

	public static final int MSG_RES_OK = R.string.msg_delete_res_ok;
	public static final int MSG_RES_FAILED = R.string.msg_delete_res_failed;
	public static final int MSG_RES_CANCEL = R.string.msg_delete_res_cancel;

	private static final int MSG_SHOW_PROGRESS_DIALOG = R.string.msg_delete_show_progress_dialog;
	// private static final int MSG_UPDATE_PROGRESS =
	// R.string.msg_delete_update_progress;
	private static final int MSG_DISMISS_ALL_DIALOG = R.string.msg_delete_dismiss_all_dialog;

	private static final int STATUS_CLIP_NO_SYS = 0;
	private static final int STATUS_CLIP_HAS_SYS = 1;
	private static final int STATUS_CLIP_ALL_SYS = 2;
	private static BaseActivity instance;

	public static class FileDeleteThread extends FileThread {
		private static final String TAG = "FileDeleteThread";

		public FileDeleteThread(BaseActivity ba) {
			super(ba, ba.getHandler());
			instance = ba;
		}

		private void onShowProgDlg() {
			sendMsg(MSG_SHOW_PROGRESS_DIALOG);
		}

		// update progress directly in thread;
		private void onUdpateProgress() {
			// sendMsg(MSG_UPDATE_PROGRESS);
			if (null != sProgDlg)
				sProgDlg.incrementProgressBy(1);
		}

		private void onDismissProgDlg() {
			Log.i(TAG, "==> onDismissProgDlg");
			sendMsg(MSG_DISMISS_ALL_DIALOG);
		}

		private void onDeleteOk() {
			sendMsg(MSG_RES_OK);
		}

		private void onDeleteCancel() {
			sendMsg(MSG_RES_CANCEL);
		}

		private void getFileCount(File file) {
			if (isStop() || null == file || !file.exists()) {
				return;
			}

			if (file.isDirectory()) {
				File[] files = file.listFiles();
				if (isStop() || 0 == files.length)
					return;

				if (files.length > 0) {

					int i;
					for (i = 0; i < files.length; i++) {
						getFileCount(files[i]);
					}
				}
			} else {
				siFileCount++;
			}
		}

		private void getFileCount(List<File> fileList) {
			if (isStop() || 0 == fileList.size()) {
				return;
			}

			for (File file : fileList) {
				if (isStop() || !file.exists()) {
					break;
				}
				getFileCount(file);
			}
		}

		protected void delete(File file) {
			Log.d(TAG,
					"the delete file is ============" + file.getAbsolutePath());
			Log.d(TAG, "==> not upload or download");
			if (file.isDirectory()) {
				File[] childs = file.listFiles();
				if (childs.length > 0) {
					int i;
					for (i = 0; i < childs.length; i++) {
						if (isStop() || !childs[i].exists())
							break;
						delete(childs[i]);
						if (sbNeedNotify == false) {
							sbNeedNotify = needNotify(childs[i]);
						}
					}
				}
			} else {
				if (sbNeedNotify == false) {
					sbNeedNotify = needNotify(file);
				}
			}

			// if the directory is empty, delete it directly.
			// if the directory is not empty,empty it before delete.
			// delete file or directory which is empty
			if (!isStop() || file.exists()) {
				file.delete();
				// siCurProg++;
				onUdpateProgress();
			}
			// end
		}

		private boolean needNotify(File file) {
			if (null == file || !file.exists()) {
				Log.e(TAG, "invalid parameter in needNotify");
				return false;
			} else {
				if (file.isDirectory())
					return false;

				String type = FileUtil.getMimeTypeOfFile(sActivity, file);
				if (null != type) {
					if (type.startsWith("image") || type.startsWith("audio")
							|| type.startsWith("video")) {
						return true;
					}
				}
				return false;
			}
		}

		protected void realRun() {
			super.realRun();

			getFileCount(slFiles);

			if (!isStop() && siFileCount > 1) {
				onShowProgDlg();
			}

			for (File file : slFiles) {
				if (isStop() || !file.exists())
					break;

				delete(file);

				// remove the file in clip
				if (!isStop())
					FileClipBoard.getInstance().removeFile(file);
			}

			onDismissProgDlg();
			if (!isStop())
				onDeleteOk();
			else {
				onDeleteCancel();
			}

			if (sbNeedNotify) {
				if (1 == siFileCount && null != slFiles.get(0)) {
					Log.d(TAG, "[notify mediascanner] delete one file");
					Log.d(TAG, "slFiles.get(0)=========" + slFiles.get(0));
					FileUtil.notifyMediaScanner(sActivity, slFiles.get(0));
				} else {
					Log.d(TAG, "[notify mediascanner] delete files");
					FileUtil.notifyMediaScanner(sActivity, null);
				}
				sbNeedNotify = false;
			}
		}
	}

	private static BaseActivity sActivity = null;
	private static ProgressDialog sProgDlg = null;
	private static ProgressDialog sWaitDlg = null;
	private static FileDeleteThread sDeleteThread = null;

	private static boolean sbNeedNotify = false;
	private static int siFileCount = 0;
	// private static int siCurProg = 0;
	private static List<File> slFiles = null;

	private static FileClipBoard sClipBoard = null;
	private static int sSysFlag = -1;

	private static void udpateProgress() {
		if (null != sProgDlg) {
			// sProgDlg.setProgress(siCurProg);
			sProgDlg.incrementProgressBy(1);
		}
	}

	private static void dismissAllDlg() {
		if (null != sProgDlg) {
			sProgDlg.dismiss();
			sProgDlg = null;
		}
		if (null != sWaitDlg) {
			sWaitDlg.dismiss();
			sWaitDlg = null;
		}
	}

	private static void showProgDlg() {
		if (null == sProgDlg) {
			sProgDlg = new ProgressDialog(sActivity);
			sProgDlg.setTitle(R.string.delete_progress);
			sProgDlg.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
			sProgDlg.setCancelable(true);
			sProgDlg.setMax(siFileCount);
			sProgDlg.setButton(sActivity.getText(R.string.alert_dialog_cancel),
					new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog,
								int whichButton) {
							// User clicked No so do some stuff
							if (sDeleteThread != null) {
								Log.d(TAG,
										"(((((((((((((((((((((((((((((((((((((");
								// sDeleteThread.stopIt();//add 2012-12-13 by
								// xqm
								sDeleteThread.stop();// add 2012-12-13 by xqm
								sActivity.sendEmptyMsg(MSG_RES_CANCEL);
							}
							sDeleteThread = null;
						}
					});
		}

		if (null != sProgDlg) {
			sProgDlg.show();
		}
	}

	private static void showWaitDialog() {
		if (null == sWaitDlg) {
			sWaitDlg = new ProgressDialog(sActivity);
			sWaitDlg.setTitle(R.string.delete_file);
			sWaitDlg.setMessage(sActivity.getString(R.string.waiting_deleting));
			sWaitDlg.setCancelable(false);
			// add 2010-12-13 by xqm
			sWaitDlg.setButton(sActivity.getText(R.string.alert_dialog_cancel),
					new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog,
								int whichButton) {
							// User clicked No so do some stuff
							if (sDeleteThread != null) {
								Log.d(TAG,
										"#######################################33");
								sDeleteThread.stop();
							}
							sDeleteThread = null;
							dialog.cancel();
						}
					});
			// end
			// mProgressDialog.setDefaultButton(false);
		}

		if (null != sWaitDlg) {
			Log.d(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@2");
			sWaitDlg.show();
		}
	}

	private static void initHandler() {
		// show progress dialog
		FileHandler.MsgHandleFunc handler = new FileHandler.MsgHandleFunc() {
			// @Override
			public boolean onMessage(Message msg) {
				// TODO Auto-generated method stub
				if (null != sWaitDlg) {
					sWaitDlg.dismiss();
					sWaitDlg = null;
				}
				showProgDlg();
				return false;
			}
		};
		sActivity.addMsgHandler(MSG_SHOW_PROGRESS_DIALOG, handler);

		// // update progress
		// handler = new FileHandler.MsgHandleFunc() {
		// // @Override
		// public boolean onMessage(Message msg) {
		// // TODO Auto-generated method stub
		// udpateProgress();
		// return false;
		// }
		// };
		// sActivity.addMsgHandler(MSG_UPDATE_PROGRESS, handler);

		// dismiss all dialogs
		handler = new FileHandler.MsgHandleFunc() {
			// @Override
			public boolean onMessage(Message msg) {
				// TODO Auto-generated method stub
				dismissAllDlg();
				return false;
			}
		};
		sActivity.addMsgHandler(MSG_DISMISS_ALL_DIALOG, handler);
	}

	private static void initData() {
		sbNeedNotify = false;
		siFileCount = 0;
		// siCurProg = 0;
		if (null == slFiles) {
			slFiles = new ArrayList<File>();
		}
	}

	private static void fillData(File file) {
		if (null == slFiles) {
			slFiles = new ArrayList<File>();
		} else {
			slFiles.clear();
		}
		slFiles.add(file);
	}

	private static void fillDataFromClip() {
		if (null == slFiles) {
			slFiles = new ArrayList<File>();
		} else {
			slFiles.clear();
		}
		slFiles.addAll(FileClipBoard.getInstance().getItemsInList());
	}

	private static void init() {
		initData();
		initHandler();
	}

	private static void deleteFile(File file) {
		init();
		fillData(file);
		// showWaitDialog();//add 2010-12-13 by xqm
		Log.d(TAG, "the operator file is ============" + file.getAbsolutePath());
		deleteFileInThread();
	}

	private static void deleteFileInClip() {
		if (sSysFlag != STATUS_CLIP_NO_SYS) {
			protectSysFileInClip();
		}

		if (sClipBoard.isEmpty()) {
			return;
		} else {
			init();
			fillDataFromClip();
			// showWaitDialog();//add 2010-12-13 by xqm
			deleteFileInThread();
		}
	}

	private static void deleteFileInThread() {
		sDeleteThread = new FileDeleteThread(sActivity);
		sDeleteThread.start();
	}

	private static void checkFileThenDel(final File file) {
		Log.i(TAG, "==> checkFileThenDel");
		DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
			// @Override
			public void onClick(DialogInterface dialog, int which) {
				// TODO Auto-generated method stub
				deleteFile(file);
			}
		};

		FileDialog.DialogButton dbp = new FileDialog.DialogButton(
				R.string.alert_dialog_ok, listener);

		// [improve] for protect system file
		if (file.isDirectory()) {
			if (file.getName().equals("gpsmap")) {
				FileDialog.showMsgWithTwoButton(sActivity,
						R.string.dlg_delete_title,
						R.string.alert_dialog_delete_gpsmap, dbp,
						FileDialog.DEFAULT_BUTTON_CANCEL);
			} else {
				FileDialog.showMsgWithTwoButton(sActivity,
						R.string.dlg_delete_title,
						R.string.alert_dialog_delete_dir, dbp,
						FileDialog.DEFAULT_BUTTON_CANCEL);
			}
		} else if (file.isFile()) {
			FileDialog.showMsgWithTwoButton(sActivity,
					R.string.dlg_delete_title,
					R.string.alert_dialog_delete_file, dbp,
					FileDialog.DEFAULT_BUTTON_CANCEL);
		}
	}

	private static void checkClipThenDel() {
		Log.i(TAG, "==>onDelete");

		if (sClipBoard.isEmpty()) {
			Toast.makeText(sActivity, R.string.nosource, Toast.LENGTH_SHORT)
					.show();
			return;
		}

		int gpsmap_flag = 0;
		int amount = 0;

		for (File file : sClipBoard.getItemsInList()) {
			// [improve]
			if (FileUtil.isSysFile(file))
				amount++;
		}

		// 1 ==> has sys
		// 2 ==> all sys
		// 0 ==> no sys
		if (0 == amount) {
			sSysFlag = STATUS_CLIP_NO_SYS;
		} else if (amount == sClipBoard.getSize()) {
			sSysFlag = STATUS_CLIP_ALL_SYS;
		} else {
			sSysFlag = STATUS_CLIP_HAS_SYS;
		}

		if (sClipBoard.hasIt(FileUtil.GPS_MAP_DIR)) {
			gpsmap_flag = 1;
		} else {
			gpsmap_flag = 0;
		}

		FileDialog.DialogButton dbp = new FileDialog.DialogButton(
				R.string.alert_dialog_ok,
				new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						deleteFileInClip();
					}
				});

		FileDialog.DialogButton dbn = new FileDialog.DialogButton(
				R.string.dlg_btn_cancel, new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						sClipBoard.setOperation(FileClipBoard.OP_NONE);
					}
				});

		// [improve]
		if (sSysFlag == STATUS_CLIP_HAS_SYS) {
			if (sClipBoard.getSize() > 1) {
				if (gpsmap_flag == 1) {
					// case [more file][has sys][has gpsmap]
					FileDialog.showMsgWithTwoButton(sActivity,
							R.string.dlg_delete_title,
							R.string.alert_dialog_del_sys_gpsmap, dbp, dbn);
				} else {
					// case [more file][has sys][no gpsmap]
					FileDialog
							.showMsgWithTwoButton(sActivity,
									R.string.dlg_delete_title,
									R.string.dlg_delete_msg_multifiles_hassys,
									dbp, dbn);
				}
			} else {
				// case [one file][has sys]
				// no this case, flag should be 2
			}
		} else if (sSysFlag == STATUS_CLIP_NO_SYS) {
			if (sClipBoard.getSize() > 1) {
				if (gpsmap_flag == 1) {
					// case [more file][no sys][has gpsmap]
					FileDialog.showMsgWithTwoButton(sActivity,
							R.string.dlg_delete_title,
							R.string.alert_dialog_delete_some_gpsmap, dbp, dbn);
				} else {
					// case [more file][no sys][no gpsmap]
					FileDialog.showMsgWithTwoButton(sActivity,
							R.string.dlg_delete_title,
							R.string.dlg_delete_msg_multifiles, dbp, dbn);
				}
			} else if (sClipBoard.getSize() == 1) {
				if (sClipBoard.getFile(0).isDirectory()) {
					if (gpsmap_flag == 1) {
						// case [one file][no sys][has gpsmap]
						FileDialog.showMsgWithTwoButton(sActivity,
								R.string.dlg_delete_title,
								R.string.alert_dialog_delete_gpsmap, dbp, dbn);

					} else {
						// case [one file][no sys][no gpsmap]
						FileDialog.showMsgWithTwoButton(sActivity,
								R.string.dlg_delete_title,
								R.string.alert_dialog_delete_dir, dbp, dbn);
					}
				} else if (sClipBoard.getFile(0).isFile()) {
					FileDialog.showMsgWithTwoButton(sActivity,
							R.string.dlg_delete_title,
							R.string.alert_dialog_delete_file, dbp, dbn);
				}
			}
		} else if (sSysFlag == STATUS_CLIP_ALL_SYS) {
			if (sClipBoard.getSize() > 1) {
				// case [more file][all sys]
				FileDialog.showMsgWithOneButton(sActivity,
						R.string.dlg_delete_title,
						R.string.dlg_delete_msg_multifiles_allsys,
						FileDialog.DEFAULT_BUTTON_OK);
			} else {
				// case [one file][all sys]
				if (sClipBoard.getFile(0).isFile()) {
					FileDialog.showMsgWithOneButton(sActivity,
							R.string.dlg_delete_title,
							R.string.dlg_delete_msg_onefile_sys,
							FileDialog.DEFAULT_BUTTON_OK);
				} else if (sClipBoard.getFile(0).isDirectory()) {
					FileDialog.showMsgWithOneButton(sActivity,
							R.string.dlg_delete_title,
							R.string.dlg_delete_msg_onedir_sys,
							FileDialog.DEFAULT_BUTTON_OK);
				}
			}
		}
	}

	private static void protectSysFileInClip() {
		Log.d(TAG, "==> protectSysFileInClip");

		if (STATUS_CLIP_ALL_SYS == sSysFlag) {
			sClipBoard.clear();
		} else if (STATUS_CLIP_HAS_SYS == sSysFlag) {
			List<File> list = sClipBoard.getItemsInList();
			ListIterator<File> iterator = list.listIterator(0);
			while (iterator.hasNext()) {
				File file = iterator.next();

				if (FileUtil.isSysFile(file)) {
					iterator.remove();
				}
			}
		} else if (STATUS_CLIP_HAS_SYS == sSysFlag) {
			Log.e(TAG, "no sys file in clip");
		} else {
			Log.e(TAG, "unknown status in protectSysFileInClip");
		}
	}

	// public interface
	public static void deleteOneFile(BaseActivity activity, File file) {
		Log.i(TAG, "==> deleteOneFile");

		if (null == activity || null == file || !file.exists()) {
			Log.e(TAG, "invalid parameter in deleteOneFile");
			return;
		} else {
			sActivity = activity;
			checkFileThenDel(file);
		}
	}

	public static void deleteFilesInClip(BaseActivity activity) {
		Log.i(TAG, "==> deleteInClip");

		if (null == activity) {
			Log.e(TAG, "invalid parameter in delete");
			return;
		} else {
			sClipBoard = FileClipBoard.getInstance();
			if (!sClipBoard.hasValidData()
					|| FileClipBoard.OP_DELETE != sClipBoard.getOperation()) {
				Log.e(TAG, "no valid data in clip");
			} else {
				sActivity = activity;
				checkClipThenDel();
			}
		}
	}

}
